package com.attendance.chdingtask.service;

import com.alibaba.fastjson.JSONObject;
import com.attendance.chdingtask.dao.AuthInfoDao;
import com.attendance.chdingtask.dao.BaseJPA;
import com.attendance.chdingtask.model.AuthInfo;
import com.attendance.chdingtask.model.CorpUserDetail;
import com.attendance.chdingtask.utils.FileUtils;
import com.attendance.chdingtask.utils.Logger;
import com.attendance.chdingtask.utils.dingApi.DdConfigSign;
import com.attendance.chdingtask.utils.dingApi.JwtUtils;
import com.attendance.chdingtask.utils.dingApi.UserHelper;
import com.dingtalk.api.DefaultDingTalkClient;
import com.dingtalk.api.DingTalkClient;
import com.dingtalk.api.request.OapiGetJsapiTicketRequest;
import com.dingtalk.api.request.OapiGettokenRequest;
import com.dingtalk.api.request.OapiMessageCorpconversationAsyncsendV2Request;
import com.dingtalk.api.request.OapiMessageCorpconversationRecallRequest;
import com.dingtalk.api.response.*;
import com.taobao.api.ApiException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashMap;
import java.util.Map;

@Service
public class AuthInfoDaoService extends BaseService<AuthInfo,Long> {
    private static Logger logger=Logger.getLogger(AuthInfoDaoService.class);
    /**
     * 调整到1小时50分钟
     */
    public static final long cacheTime=1000 * 60 * 55 * 2;

    @Autowired
    private AuthInfoDao dao;

    @Override
    protected BaseJPA<AuthInfo> getDao() {
        return dao;
    }

    public AuthInfo findByCorpIdAndAppKey(String corpId, String agentId) {
        return dao.findByCorpIdAndAgentId(corpId, agentId);
    }


    public String getAccessToken(AuthInfo authInfo) throws ApiException {
        long curTime=System.currentTimeMillis();
        String accToken="";
        if (null == authInfo.getExpires() || curTime - authInfo.getExpires().longValue() >= cacheTime) {
            try {
                logger.info("accToken 过期 ，重新获取...............{}..{}..{} {} {}", authInfo.getCorpId(), authInfo.getAppKey(), curTime);
                DefaultDingTalkClient client=new DefaultDingTalkClient("https://oapi.dingtalk.com/gettoken");
                OapiGettokenRequest request=new OapiGettokenRequest();
                request.setAppkey(authInfo.getAppKey());
                request.setAppsecret(authInfo.getAppSecret());
                request.setHttpMethod("GET");
                OapiGettokenResponse response=client.execute(request);
                if (!response.isSuccess()) {
                    throw new ApiException("应用获取token失败，请检查！" + response.getErrmsg());
                }
                accToken=response.getAccessToken();
                authInfo.setAccessToken(accToken);
                authInfo.setExpires(curTime);
                update(authInfo.getId(), authInfo);

            } catch (Exception e) {
                e.printStackTrace();
            }
        } else {
            logger.info("accToken 未过期 ，不需要重新获取...............{}..{}..{} {} {}", authInfo.getCorpId(), authInfo.getAppKey(), curTime, authInfo.getExpires().intValue(), authInfo.getExpires().longValue());
            accToken=authInfo.getAccessToken();
        }
        return accToken;

    }

    /**
     * 首次应用配置信息入库
     *
     * @param authInfo
     * @throws ApiException
     */
    @Transactional(propagation= Propagation.REQUIRED, rollbackFor=Exception.class)
    public void create(AuthInfo authInfo) throws ApiException {
        long curTime=System.currentTimeMillis();
        DefaultDingTalkClient client=new DefaultDingTalkClient("https://oapi.dingtalk.com/gettoken");
        OapiGettokenRequest request=new OapiGettokenRequest();
        request.setAppkey(authInfo.getAppKey());
        request.setAppsecret(authInfo.getAppSecret());
        request.setHttpMethod("GET");
        OapiGettokenResponse response=client.execute(request);
        if (!response.isSuccess()) {
            throw new ApiException("应用获取token失败，请检查！" + response.getErrmsg());
        }
        authInfo.setAccessToken(response.getAccessToken());
        authInfo.setExpires(curTime);
        save(authInfo);
    }

    private static void SendResultMsg() throws ApiException {
        DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/message/corpconversation/asyncsend_v2");
        OapiMessageCorpconversationAsyncsendV2Request request = new OapiMessageCorpconversationAsyncsendV2Request();
        request.setUseridList("162657431121341120");
        request.setAgentId(797863777L);
        request.setToAllUser(false);
        OapiMessageCorpconversationAsyncsendV2Request.Msg msg = new OapiMessageCorpconversationAsyncsendV2Request.Msg();

        msg.setActionCard(new OapiMessageCorpconversationAsyncsendV2Request.ActionCard());
        msg.getActionCard().setTitle("xxx123411111");
        msg.getActionCard().setMarkdown("### 测试123111  \n<font color=#0099ff size=3 face=\"黑体\">已处理</font>");
        msg.getActionCard().setSingleTitle("测试测试");
        msg.getActionCard().setSingleUrl("https://www.baidu.com");
        msg.setMsgtype("action_card");
        request.setMsg(msg);
        OapiMessageCorpconversationAsyncsendV2Response response = client.execute(request,"30f60814a8f8321fb25509054943579a");
        System.out.println(response.getTaskId());
    }

    private static void callBackMsg(Long taskId) throws ApiException {
        DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/message/corpconversation/recall");
        OapiMessageCorpconversationRecallRequest request = new OapiMessageCorpconversationRecallRequest();
        request.setAgentId(797863777L);
        request.setMsgTaskId(taskId);
        OapiMessageCorpconversationRecallResponse response = client.execute(request, "30f60814a8f8321fb25509054943579a");
    }



    public CorpUserDetail login(AuthInfo authInfo) throws ApiException {
        long time=System.currentTimeMillis();
        AuthInfo info=dao.findByCorpIdAndAgentId(authInfo.getCorpId(),authInfo.getAgentId());
        if(null == info){
            throw new ApiException("应用信息未注册，请先注册应用");
        }
        logger.info("免登时间:{}  ", System.currentTimeMillis() - time);
        String accessToken=getAccessToken(info);
        String userId= UserHelper.getUserIdInfo(accessToken,authInfo.getCode());
        OapiV2UserGetResponse.UserGetResponse userGetResponse=UserHelper.getUserInfoDetail(accessToken,userId);
        CorpUserDetail userDetail=new CorpUserDetail();
        userDetail.setUserid(userGetResponse.getUserid());
        userDetail.setAvatar(userGetResponse.getAvatar());
        userDetail.setName(userGetResponse.getName());
        userDetail.setMobile(userGetResponse.getMobile());
        userDetail.setCorpId(authInfo.getCorpId());
        userDetail.setDepartment(userGetResponse.getDeptIdList().toString());
        userDetail.setAppId(info.getId());
        String sign= JwtUtils.sign(userDetail, 30L * 24L * 3600L * 1000L);
        logger.info("签名token为：{} ", sign);
        userDetail.setToken(sign);
        return userDetail;
    }

    public Object getConfig(String url, AuthInfo info) {
        /**
         * 确认url与配置的应用首页地址一致
         */
        System.out.println(url);
        /**
         * 随机字符串
         */
        String nonceStr = "abcdefg";
        long timeStamp = System.currentTimeMillis() / 1000;
        String signedUrl = url;
        String ticket = null;
        String signature = null;
        try {
            String  accessToken = getAccessToken(info);
            ticket = getJsapiTicket(accessToken,info);
            signature = DdConfigSign.sign(ticket, nonceStr, timeStamp, signedUrl);
        } catch (Exception e) {
            logger.error("签名失败！"+e.getMessage());
            e.printStackTrace();
        }
        Map<String, Object> configValue = new HashMap<>();
        configValue.put("jsticket", ticket);
        configValue.put("signature", signature);
        configValue.put("nonceStr", nonceStr);
        configValue.put("timeStamp", timeStamp);
        configValue.put("corpId",info.getCorpId());
        configValue.put("agentId", info.getAgentId());
        return configValue;

    }
    /**
     * 获取JSTicket, 用于js的签名计算
     * 正常的情况下，jsapi_ticket的有效期为7200秒，所以开发者需要在某个地方设计一个定时器，定期去更新jsapi_ticket
     */
    public  String getJsapiTicket(String accessToken,AuthInfo info) throws ApiException {
        JSONObject jsTicketValue = (JSONObject) FileUtils.getValue("jsticket", info.getAppKey());
        long curTime = System.currentTimeMillis();
        String jsTicket = "";
        if (jsTicketValue == null || curTime -
                jsTicketValue.getLong("begin_time") >= cacheTime) {
            try {
                DefaultDingTalkClient client=new DefaultDingTalkClient("https://oapi.dingtalk.com/get_jsapi_ticket");
                OapiGetJsapiTicketRequest req=new OapiGetJsapiTicketRequest();
                req.setTopHttpMethod("GET");
                OapiGetJsapiTicketResponse execute=client.execute(req, accessToken);
                if (!execute.isSuccess()) {
                    throw new ApiException("jsapi_ticket获取失败，请检查！");
                }
                jsTicket=execute.getTicket();
                JSONObject jsonTicket=new JSONObject();
                JSONObject jsontemp=new JSONObject();
                jsontemp.clear();
                jsontemp.put("ticket", jsTicket);
                jsontemp.put("begin_time", curTime);
                jsonTicket.put(info.getCorpId(), jsontemp);
                FileUtils.write2File(jsonTicket, "jsticket");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }else{
            jsTicket=jsTicketValue.getString("ticket");
        }
        return jsTicket;
    }
}
